/**
 * Copyright © 2022-2023 AsiaInfo Technologies Limited.
 * All Rights Reserved.
 * -
 * This software is the confidential and proprietary information of
 * AsiaInfo Technologies Limited.
 * ("Confidential Information"). You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with asiainfo.
 * -
 * ASIAINFO MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE, OR NON-INFRINGEMENT.ASIAINFO SHALL NOT BE LIABLE FOR
 * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
 * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 */
package com.wy.common.util.tree;

import com.wy.entity.SysDept;

import java.io.Serializable;
import java.util.*;

/**********************************************************
 * Copyright © 2022,亚信科技(中国)有限公司
 * All Rights Reserved.
 * 文件名称： TreeBuilder.java
 * 摘 要： [树形结构构造器]
 * 初始版本：1.0.0
 * 原 作 者：zhangwenbo
 * 完成日期： 2022年4月28日 下午20时49分29秒
 * 当前版本： 1.0.0
 * 作 者： zhangwenbo
 * 完成日期： 2022年4月28日 下午20时49分29秒
 *****************************************************************/

/**
 * @param <T>
 *            实体
 * @param <P>
 *            主键
 */
public class TreeBuilder<T extends TreeFormat<T, P>, P extends Serializable> {

    /**
     * 新建一个树形构造器.
     *
     * @param clazz
     *            定义的实体
     * @param pk
     *            主键
     * @param <E>
     *            实体
     * @param <P>
     *            主键
     * @return 格式化树形
     */
    public static <E extends TreeFormat<E, P>, P extends Serializable> TreeBuilder<E, P> newTreeBuilder(
        Class<E> clazz, Class<P> pk) {
        return new TreeBuilder<E, P>();
    }

    /**
     * 生成树集合.
     *
     * @param origin
     *            集合
     * @return 树集合
     */
    public Set<T> buildToTreeSet(Collection<T> origin) {
        Set<T> target = new HashSet<T>();
        toTreeFormat(origin, target);
        return target;
    }

    /**
     * 生成树集合.
     *
     * @param origin
     *            集合
     * @return 树集合
     */
    public List<T> buildToTreeList(Collection<T> origin) {
        List<T> target = new ArrayList<T>();
        toTreeFormat(origin, target);
        return target;

    }

    /**
     * 格式化树形.
     *
     * @param origin
     *            源集合
     * @param target
     *            目标集合
     */
    private void toTreeFormat(Collection<T> origin, Collection<T> target) {
        LinkedList<T> queue = new LinkedList<T>();
        Map<P, T> cache = new HashMap<P, T>();
        // 第一轮循环找到根节点. 初始化队列.
        for (T data : origin) {
            if (data.getTreeParentId() == null) {
                target.add(data);
            } else {
                queue.add(data);
            }
            cache.put(data.getTreeId(), data);
        }
        while (!queue.isEmpty()) {
            int queueSize = queue.size();
            for (int i = 0; i < queueSize; i++) {
                T data = queue.poll();
                T parent = cache.get(data.getTreeParentId());
                if (parent != null) {
                    parent.addChildren(data);
                } else {
                    queue.add(data);
                }
            }
            if (queue.size() == queueSize) {
                for (int i = 0; i < queueSize; i++) {
                    target.add(queue.poll());
                }
            }
        }
    }

}
